module Main where
import System.IO
import Numeric

show1::Double->String
show1 x= showFFloat (Just 10) x ""


generate_sphere_points::Int->Int->[(Double,Double,Double)]
generate_sphere_points m n =myfun 0 m n [(0,0,-1),(0,0,(1))]
    where
        pi=acos (-1.0)
        step1=pi/(realToFrac $ n+1 ::Double)
        step2=2*pi/(realToFrac $ m ::Double)
        myfun ::Int->Int->Int->[(Double,Double,Double)]->[(Double,Double,Double)]
        myfun num m1 n1 r1=if num >=m1*n1
            then r1
            else 
                ---myfun (num+1) m1 n1 $ (1,1,1):r1
                myfun (num+1) m1 n1 $ (sin ((t1+1)*step1)*cos (t2*step2),sin ((t1+1)*step1)*sin (t2*step2),cos ((t1+1)*step1)):r1
                where
                    t1=realToFrac $ div num m1::Double
                    t2=realToFrac $ mod num m1::Double



generate_sphere_indexs::Int->Int->[(Int,Int,Int)]
generate_sphere_indexs m n=if m<=2 || n<1 
    then []
    else myfun 0 m n []
        where 
            myfun1:: Int->Int->Int->(Int,Int,Int)
            myfun1 num m1 n1=if num<m1
                then (num+2,(mod (num+1) m1)+2,0)
                else if num >= 2*m1*n1-m1
                then (t+(n1-1)*m1 +2,(mod (t-1) m1)+(n1-1)*m1 +2,1)
                else if mod t1 2 ==0
                then (t2 + 2,t2+ m1 +2,t3*m1+ mod (t2+1) m1 +m1 + 2)
                else (t2+2,t3*m1+mod (t2+1) m1+m1 +2,t3*m1+mod (t2+1) m1+2)
                    where 
                        t=num-2*m1*n1+m1
                        t1=num-m1
                        t2=div t1 2
                        t3=div t2 m1
                  
            myfun:: Int->Int->Int->[(Int,Int,Int)]->[(Int,Int,Int)]
            myfun num m1 n1 r1=if num>=2*m1*n1 
                then r1
                else 
                    myfun (num+1) m1 n1 $ (myfun1 num m1 n1):r1

generate_sphere_off:: Int->Int->(Double,Double,Double)->Double->IO()
generate_sphere_off m n (o1,o2,o3) r=do
    h1<- openFile "sphere.off" WriteMode
    hPutStrLn h1 "OFF"
    hPutStrLn h1 $ (show $ m*n+2)++ " "++(show $ 2*m*n) ++" 0"  
    myfun h1 $  map (\(a,b,c)->(r*a+o1 ,r*b+o2,r*c+o3)) $generate_sphere_points m n
    myfun1 h1 $ generate_sphere_indexs m n
    hClose h1
    where 
        myfun1::Handle->[(Int,Int,Int)]->IO()  
        myfun1 _ []= do
            return ()
        myfun1 h (x:xs)=do
            myfun1 h xs
            (\(a,b,c)->hPutStrLn h $ "3 "++(show  a)++" "++(show b) ++" "++ (show c))x 
        myfun::Handle->[(Double,Double,Double)]->IO()  
        myfun _ []= do
            return ()
        myfun h (x:xs)=do
            myfun h xs
            (\(a,b,c)->hPutStrLn h $ (show1  a)++" "++(show1 b) ++" "++ (show1 c))x
            --hPutStrLn h "d"


main :: IO ()
main = do
    generate_sphere_off 20 19 (1,1,1) 2
    test_fun
    putStrLn $ show $ generate_sphere_points 4 2
    --putStrLn $show $ generate_sphere_indexs 4 2 
    return ()
    where 
        test_fun:: IO()
        test_fun=putStrLn "hello"


main1 :: IO ()
main1 = do
    let  
        test_fun:: IO()
        test_fun=putStrLn "hello"
    test_fun

main2 :: IO ()
main2 = let  
            test_fun:: IO()
            test_fun=putStrLn "hello"
        in do
            test_fun
